package handler

import (
	"github.com/gin-gonic/gin"
	"github.com/lab-online/internal/class/constant"
	"github.com/lab-online/internal/class/entity"
	vo "github.com/lab-online/internal/shared/valueobject"
	"github.com/lab-online/pkg/auth"
	mw "github.com/lab-online/pkg/middleware"
	"github.com/lab-online/pkg/resp"
	"github.com/lab-online/pkg/util"
)

type updateStudentReqBodyItem struct {
	OP    string   `json:"op" binding:"required,oneof=add remove replace" example:"add"`         // 操作类型
	Value []string `json:"value" binding:"required,gt=0,dive,len=8" example:"20240206,20240207"` // 需要操作的学生学号
}
type updateStudentReqBody = []updateStudentReqBodyItem

type updateStudentReqParams struct {
	ClassID uint `uri:"id" binding:"required" example:"1"` // 班级id
}

var UpdateStudentValidator = mw.NewValidator(func() *mw.ValidatorOptions {
	return &mw.ValidatorOptions{
		Body:   &updateStudentReqBody{},
		Params: &updateStudentReqParams{},
	}
})

type studentInfo struct {
	Name     string `json:"name" binding:"required" example:"张三"`           // 学生姓名
	Username string `json:"username" binding:"required" example:"20240206"` // 学生学号
	Role     uint   `json:"role" binding:"required" example:"1"`            // 学生角色
}
type updateStudentRespData []studentInfo

type UpdateStudentRespBody struct {
	resp.BaseRespBody
	Data updateStudentRespData `json:"data" binding:"required"`
}

type updateStudentFailedRespData struct {
	Usernames []string `json:"username" binding:"required" example:"20240206"` // 错误的用户
	Message   string   `json:"msg" binding:"required" example:"用户不存在"`         // 失败原因
}
type UpdateStudentFailedRespBody struct {
	resp.BaseRespBody
	Data updateStudentFailedRespData `json:"data" binding:"required"`
}

// UpdateStudent 更新班级学生
//
//	@Summary				更新班级学生
//	@Description.markdown	UpdateStudent
//	@Description			## 规则
//	@Description			教师可以管理 `Teacher` 为自己的班级，管理员可以管理任何班级
//	@Description			Todo
//	@Tags					class
//	@Accept					json
//	@Produce				json
//	@Security				bearer
//	@Param					Authorization	header		string					true	"`teacher` | `admin`"
//	@Param					classID			path		uint					true	"班级id"
//	@Param					class			body		updateStudentReqBody	true	"班级信息"
//	@Success				200				{object}	UpdateStudentRespBody
//	@Failure				400				{object}	resp.FailedRespBodyString
//	@Failure				400				{object}	UpdateStudentFailedRespBody
//	@Failure				403				{object}	resp.FailedRespBodyString
//	@Failure				500				{object}	resp.FailedRespBodyString
//	@x-apifox-status		"developing"
//	@Router					/v1/classes/:classID/students	[patch]
func (h *Handler) UpdateStudent(c *gin.Context) {
	authEntity := c.MustGet(auth.KeyAuth).(auth.AuthEntity)
	patches := c.MustGet(mw.KeyBody).(*updateStudentReqBody)
	classID := c.MustGet(mw.KeyParams).(*updateStudentReqParams).ClassID

	studentPatches := util.SliceMap(*patches, func(patch updateStudentReqBodyItem) vo.PatchVO {
		return vo.NewPatch(
			vo.WithPatchOP[[]string](patch.OP),
			vo.WithPatchValue(patch.Value),
		)
	})

	classEntity := entity.NewClassEntity(entity.WithID(classID))
	classEntity, e := h.domain.UpdateStudent(studentPatches, classEntity, authEntity)

	switch {
	case e != nil && classEntity != nil:
		restErr := resp.ParseRESTError(e)
		resp.BadRequest(c, restErr.GetCode(), &updateStudentFailedRespData{
			classEntity.GetStudents(),
			restErr.GetMessage(),
		})
	case e != nil:
		resp.ErrorHandler(c, e)
	default:
		resp.Success(c, constant.CodeUpdateStudentSuccess, util.SliceMap(
			classEntity.GetStudentVOs(),
			func(user vo.UserVO) studentInfo {
				return studentInfo{
					Name:     user.GetName(),
					Username: user.GetUsername(),
					Role:     user.GetRole(),
				}
			}),
		)
	}
}
